﻿Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Reflection

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class PropertySegment
        ' Methods
        Public Sub New(ByVal serviceProvider As IServiceProvider, ByVal obj As Object)
            Me.serviceProvider = serviceProvider
            Me.obj = obj
        End Sub

        Friend Sub New(ByVal serviceProvider As IServiceProvider, ByVal obj As Object, ByVal propertyDescriptor As PropertyDescriptor)
            Me.serviceProvider = serviceProvider
            Me.obj = obj
            Me.propertyDescriptor = propertyDescriptor
        End Sub

        Friend Sub New(ByVal serviceProvider As IServiceProvider, ByVal obj As Object, ByVal [property] As PropertyInfo)
            Me.serviceProvider = serviceProvider
            Me.obj = obj
            Me.property = [property]
        End Sub

        Private Function GetComponent(ByVal obj As Object, ByVal serviceProvider As IServiceProvider) As IComponent
            Dim component As IComponent = [TryCast](obj,IComponent)
            If (((component Is Nothing) OrElse (component.Site Is Nothing)) AndAlso (Not serviceProvider Is Nothing)) Then
                Dim service As IReferenceService = [TryCast](serviceProvider.GetService(GetType(IReferenceService)),IReferenceService)
                If (Not service Is Nothing) Then
                    component = service.GetComponent(obj)
                End If
            End If
            Return component
        End Function

        Friend Function GetProperties(ByVal serviceProvider As IServiceProvider) As PropertyInfo()
            Dim list As New ArrayList(MyBase.GetType.GetProperties)
            If (Not Me.property Is Nothing) Then
                list.Add(New PropertySegmentPropertyInfo(Me, Me.property))
            ElseIf (Not Me.propertyDescriptor Is Nothing) Then
                list.Add(New PropertySegmentPropertyInfo(Me, Me.propertyDescriptor))
            ElseIf (Not Me.obj Is Nothing) Then
                Dim properties As PropertyDescriptorCollection = Nothing
                Dim converter As TypeConverter = TypeDescriptor.GetConverter(Me.obj)
                If ((Not converter Is Nothing) AndAlso converter.GetPropertiesSupported) Then
                    Dim context As New DummyTypeDescriptorContext(Me.serviceProvider, Me.GetComponent(Me.obj, serviceProvider), Nothing)
                    properties = converter.GetProperties(context, Me.obj, New Attribute(0  - 1) {})
                Else
                    properties = TypeDescriptor.GetProperties(Me.obj)
                End If
                Dim descriptor As PropertyDescriptor
                For Each descriptor In properties
                    Dim memberInfo As PropertyInfo = XomlComponentSerializationService.GetProperty(Me.obj.GetType, descriptor.Name, (BindingFlags.Public Or BindingFlags.Instance))
                    If (Not memberInfo Is Nothing) Then
                        If (Helpers.GetSerializationVisibility(memberInfo) <> DesignerSerializationVisibility.Hidden) Then
                            list.Add(New PropertySegmentPropertyInfo(Me, memberInfo))
                        End If
                    Else
                        list.Add(New PropertySegmentPropertyInfo(Me, descriptor))
                        If (Not descriptor.Converter Is Nothing) Then
                            Dim context2 As New DummyTypeDescriptorContext(Me.serviceProvider, Me.GetComponent(Me.obj, serviceProvider), descriptor)
                            If descriptor.Converter.GetPropertiesSupported(context2) Then
                                Dim descriptor2 As PropertyDescriptor
                                For Each descriptor2 In descriptor.Converter.GetProperties(context2, Me.obj, New Attribute(0  - 1) {})
                                    list.Add(New PropertySegmentPropertyInfo(Me, descriptor2))
                                Next
                                [Continue] For
                            End If
                        End If
                    End If
                Next
            End If
            Return [TryCast](list.ToArray(GetType(PropertyInfo)),PropertyInfo())
        End Function


        ' Properties
        Friend ReadOnly Property [Object] As Object
            Get
                Return Me.obj
            End Get
        End Property

        Friend ReadOnly Property PropertyDescriptor As PropertyDescriptor
            Get
                Dim propertyDescriptor As PropertyDescriptor = Me.propertyDescriptor
                If (((propertyDescriptor Is Nothing) AndAlso (Not Me.obj Is Nothing)) AndAlso (Not Me.property Is Nothing)) Then
                    propertyDescriptor = TypeDescriptor.GetProperties(Me.obj).Item(Me.property.Name)
                End If
                Return propertyDescriptor
            End Get
        End Property

        Friend ReadOnly Property ServiceProvider As IServiceProvider
            Get
                Return Me.serviceProvider
            End Get
        End Property


        ' Fields
        Private obj As Object
        Private [property] As PropertyInfo
        Private propertyDescriptor As PropertyDescriptor
        Private serviceProvider As IServiceProvider
    End Class
End Namespace

